using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;

using DiceRoller.Data;
using DiceRoller.Util;

namespace DiceRoller.GUI {

  public partial class frmMain : Form {


    private InputHistory history;
    private DiceRoller.Data.DiceRoller diceRoller;

    public frmMain() {
      InitializeComponent();
      diceRoller = new DiceRoller.Data.DiceRoller();
      history = new InputHistory();
      txtDiceDisplay.ScrollBars = ScrollBars.Vertical;
      txtTarget.Text = "7";
    }

    private void btnRoll_Click(object sender, EventArgs e) {
      rollDice();
      txtNumberDice.Focus();
    }

    private void rollDice() {
      string sNumDice;
      int numDice;
      int[] rolledDice;

      sNumDice = txtNumberDice.Text;
      if(Regex.Match(sNumDice, "[0-9]+").Success && Regex.Match(txtTarget.Text, "[0-9]+").Success) {

        numDice = Convert.ToInt32(sNumDice);

        rolledDice = diceRoller.roll(numDice);

        displayDice(rolledDice);

        displaySuccesses(rolledDice);

        displayHistory();

        updateDiceNumberHistory(sNumDice);

        txtNumberDice.Text = Convert.ToString(history.Last);
      }
    }

    private void updateDiceNumberHistory(string sNumDice) {
      history.Add(sNumDice);
    }

    private void displayHistory() {
      setBotchedStatus();
      txtHistory.Text = txtSuccesses.Text + (txtSuccesses.Text.Equals("BOTCHED") ? "   " : " Successes") + " - " + txtDiceDisplay.Text + System.Environment.NewLine + txtHistory.Text;
    }

    private void displaySuccesses(int[] rolledDice) {
      txtSuccesses.Text = (exaltedSuccesses(rolledDice)).ToString();
    }

    private void displayDice(int[] rolledDice) {
      txtDiceDisplay.Text = String.Empty;
      for(int i = 0; i < rolledDice.Length; i++) {
        txtDiceDisplay.Text += (rolledDice[i]).ToString() + " ";
      }
      txtDiceDisplay.Text.Trim();
    }

    private void setBotchedStatus() {
      if(txtSuccesses.Text.Trim().Equals("0") && Misc.countElements(txtDiceDisplay.Text.Split(), "1") >= 1 && !cboDamage.Checked) {
        txtSuccesses.Text = "BOTCHED";
      }
    }

    private int exaltedSuccesses(int[] rolledDice) {
      int successes = 0;

      for(int i = 0; i < rolledDice.Length; i++) {
        if(rolledDice[i] == 0) {
          successes += cboDamage.Checked ? 1 : 2;
        }
        else if(rolledDice[i] >= Convert.ToInt32(txtTarget.Text)) {
          successes += 1;
        }
      }
      return successes;
    }

    private void txtNumberDice_KeyDown(object sender, KeyEventArgs e) {
      keyDown(sender, e);
    }

    private void keyDown(object sender, KeyEventArgs e) {
      switch(e.KeyCode) {
        case Keys.Enter:
          rollDice();
          break;
        case Keys.Escape:
          txtNumberDice.Text = "";
          txtNumberDice.Focus();
          break;
        case Keys.Up:
          if(sender.Equals(txtNumberDice)) {
            txtNumberDice.Text = Convert.ToString(history.Previous);
          }
          break;
        case Keys.Down:
          if(sender.Equals(txtNumberDice)) {
            txtNumberDice.Text = Convert.ToString(history.Next);
          }
          break;
      }
    }

    private void cboDamage_CheckedChanged(object sender, EventArgs e) {
      changeBotchedSuccessStatus();
    }

    private void changeBotchedSuccessStatus() {
      string[] dice;
      int successes;
      int zeroes;

      if(!txtSuccesses.Text.Equals(System.String.Empty)) {
        if(!txtSuccesses.Text.Equals("BOTCHED")) {
          successes = Convert.ToInt32(txtSuccesses.Text);
        }
        else {
          successes = 0;
        }


        dice = txtDiceDisplay.Text.Split(" ".ToCharArray());

        zeroes = Misc.countElements(dice, "0");

        txtSuccesses.Text = (cboDamage.Checked ? successes - zeroes : successes + zeroes).ToString();

        displayHistory();
      }
    }

  }
}
